package cn.uncode.baas.server.dto;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import cn.uncode.dal.utils.JsonUtils;
import cn.uncode.baas.server.acl.Acl;
import cn.uncode.baas.server.acl.TableAcl;
import cn.uncode.baas.server.vo.O2oVo;
import cn.uncode.baas.server.vo.One2manyVo;

public class RestTable implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -8539801603569278105L;
	
	public static final String ID = "id";
	public static final String BUCKET = "bucket";
	public static final String NAME = "name";
	public static final String REST_ACL = "restAcl";
	public static final String TABLE_ACL = "tableAcl";
	public static final String FIELD_ACL = "fieldAcl";

	
	private int id;
	private String bucket;
	private String name;
	private String restAcl;
	private String tableAcl;
	private String fieldAcl;
	private String one2many;
	private String many2one;
	
	
	private Map<String, TableAcl> fields = new HashMap<String, TableAcl>();
	private Map<String, Acl> fieldReadAcl = new HashMap<String, Acl>();
	private Map<String, Acl> fieldInsertAcl = new HashMap<String, Acl>();
	private Map<String, Acl> fieldUpdateAcl = new HashMap<String, Acl>();
	private Map<String, Acl> fieldWriteAcl = new HashMap<String, Acl>();
	private Map<String, O2oVo> many2oneMap = new HashMap<String, O2oVo>();
	private Map<String, One2manyVo> one2manyMap = new HashMap<String, One2manyVo>();
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getBucket() {
		return bucket;
	}
	public void setBucket(String bucket) {
		this.bucket = bucket;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String getRestAcl() {
		return restAcl;
	}
	
	public Acl getAclOfRest() {
		if(StringUtils.isNotBlank(restAcl)){
			Acl acl = new Acl();
			acl.fromJson(restAcl);
			return acl;
		}
		return null;
	}
	
	public void setRestAcl(String restAcl) {
		this.restAcl = restAcl;
	}
	
	public String getFieldAcl() {
		return fieldAcl;
	}
	
	public void setFieldAcl(String fieldAcl) {
		this.fieldAcl = fieldAcl;
		resolveFieldAcl();
	}
	
	public TableAcl getAclOfField(String field){
		if(fields.size() == 0){
			resolveFieldAcl();
		}
		return fields.get(field);
	}
	
	public void setTableAcl(String tableAcl) {
		this.tableAcl = tableAcl;
	}
	
	public TableAcl getAclOfTable() {
		if(StringUtils.isNotBlank(tableAcl)){
			TableAcl table = new TableAcl();
			table.fromJson(tableAcl);
			return table;
		}
		return null;
	}

	public String getKey(){
		return bucket + "_" + name;
	}
	
	public Map<String, Acl> getFieldReadAcl() {
		return fieldReadAcl;
	}
	public void setFieldReadAcl(Map<String, Acl> fieldReadAcl) {
		this.fieldReadAcl = fieldReadAcl;
	}
	public Map<String, Acl> getFieldInsertAcl() {
		return fieldInsertAcl;
	}
	public void setFieldInsertAcl(Map<String, Acl> fieldInsertAcl) {
		this.fieldInsertAcl = fieldInsertAcl;
	}
	public Map<String, Acl> getFieldUpdateAcl() {
		return fieldUpdateAcl;
	}
	public void setFieldUpdateAcl(Map<String, Acl> fieldUpdateAcl) {
		this.fieldUpdateAcl = fieldUpdateAcl;
	}
	public Map<String, Acl> getFieldWriteAcl() {
		return fieldWriteAcl;
	}
	public void setFieldWriteAcl(Map<String, Acl> fieldWriteAcl) {
		this.fieldWriteAcl = fieldWriteAcl;
	}
	public String getOne2many() {
		return one2many;
	}
	public void setOne2many(String one2many) {
		this.one2many = one2many;
		resolveOne2many();
	}
	public String getMany2one() {
		return many2one;
	}
	
	public void setMany2one(String many2one) {
		this.many2one = many2one;
		resolveMany2one();
	}
	
	
	public Map<String, O2oVo> getMany2oneMap() {
		return many2oneMap;
	}
	public void setMany2oneMap(Map<String, O2oVo> many2oneMap) {
		this.many2oneMap = many2oneMap;
	}
	public Map<String, One2manyVo> getOne2manyMap() {
		return one2manyMap;
	}
	public void setOne2manyMap(Map<String, One2manyVo> one2manyMap) {
		this.one2manyMap = one2manyMap;
	}
	private void resolveOne2many() {
		//{{"one":"id","many":{"table":"restfield","field":"id","display":"name","order":"id"},
		// "join":{"table":"method2field","field":"restMethodId","field2":"restFieldId"}}}
        if(StringUtils.isNotEmpty(one2many)){
        	Map<?, ?> o2m = JsonUtils.fromJson(one2many, Map.class);
        	if(o2m != null){
        		Iterator<?> iter = o2m.keySet().iterator();
        		while(iter.hasNext()){
        			String key = String.valueOf(iter.next());
        			Map<?,?> valueMap = (Map<?, ?>) o2m.get(key);
        			one2manyMap.put(key, One2manyVo.valueOf(valueMap));
        		}
        	}
        }
	}
	
	private void resolveMany2one() {
		//{"bucket":{"table":"restapp","field":"bucket","display":"name","order":"id"},
        // "methodId":{"table":"restmethod","field":"id","display":"name,version","order":"id"}}
        if(StringUtils.isNotEmpty(many2one)){
        	Map<?, ?> m2o = JsonUtils.fromJson(many2one, Map.class);
        	if(m2o != null){
        		Iterator<?> iter = m2o.keySet().iterator();
        		while(iter.hasNext()){
        			String key = String.valueOf(iter.next());
        			Map<?,?> map = (Map<?, ?>) m2o.get(key);
        			if(map != null){
        				many2oneMap.put(key, O2oVo.valueOf(map));
        			}
        		}
        	}
        }
	}
	
	private void resolveFieldAcl(){
		if(StringUtils.isNotBlank(fieldAcl)){
			Map<?,?> map = JsonUtils.fromJson(fieldAcl, Map.class);
			Iterator<?> iter = map.keySet().iterator();
			while(iter.hasNext()){
				String key = String.valueOf(iter.next());
				String value = String.valueOf(map.get(key));
				TableAcl table = new TableAcl();
				table.fromJson(value);
				if(table.getRead() != null){
					fieldReadAcl.put(key, table.getRead());
				}
				if(table.getInsert() != null){
					fieldInsertAcl.put(key, table.getInsert());
				}
				if(table.getWrite() != null){
					fieldWriteAcl.put(key, table.getWrite());
				}
				if(table.getUpdate() != null){
					fieldUpdateAcl.put(key, table.getUpdate());
				}
				fields.put(key, table);
			}
		}
	}

}
